﻿//  ----------------------------------------------------------------------------
// --- Page Stack Detector --- GBitsetSteckt.h ---
// Подпрограмма распознования вертикальных стеков в пределах строки.
//  ----------------------------------------------------------------------------

void GBitset::pageStackDetector () {




TIME_START

        if( NStrok<0) { return; }



//// стеки отключены
        // Запуск подпрограммы предвармтельнного определения наличия стеков
                      PredvStackDetector();  // StackArgument, WorldArgument

        // Запуск подпрограммы окончательного определения наличия стеков
                      FlagStackDetector();

        // получили маркер (в структуре) на наличие стека вместо коренной буквы.





        if(GrafT[6][0]) { DM(END); DM(66666<<" pageStackDetector ");  DM(END); }
//          DP(END); DP(5555<<" pageStackDetector ");  DP(END);

//****************************************************************************//
       // Визуализация букв темно синими квадратиками из структур //
	   if( GrafT[6][6] ) { wordDraw(0x00AA0011); }  // темно синий
       // получили маркер (в структуре) на наличие стека вместо коренной буквы.
//****************************************************************************//

TIME_PRINT

/*
       // Запуск подпрограммы распознования пробелов в пределах строки.
////                RecognitionSpace();

        // Запуск подпрограммы получения координат прямоугольников вокруг стеков.
                    SquareStackDetector();
        // Запуск подпрограммы распознования стеков в пределах строки.
                    RecognitionStack();
*/

}//_____________________________________________________________________________



//  ----------------------------------------------------------------------------
// Запуск подпрограммы предвармтельнного определения наличия стеков
// задача не пропустить стек и отсеить прямоугольников заведомо с коренными буквами
//  ----------------------------------------------------------------------------
void GBitset::PredvStackDetector(){


  int y,x,p,d; // ,m,n
  int y0,y1,x0,x1,s0,s1,s3,s4,s5,sy0,sy1;
  int DltNstrN,DltNstrNKh,nrow;
  int NWord,res,maxres,Prg1,Prg2,LimY1;


       // для визуализации одной строки заремачить цикл по NStrok. Nstr-глобальная.
       Nstr=2;

       // вычисление максимального размера вертикального массива BufW
       nrow=hStrMax*2+1;
       vector<int> BufW(nrow);


////////////////////////////////////////////////////////////////////////////////


   int NStrok = strArray->size();
   for ( Nstr=0; Nstr < NStrok; Nstr++ ){ // Цикл по количеству строк NStrok
       // получение оптимального коэффициента вертикальной фильтрации для каждой строки
       DltNstrN = strArray[0][Nstr].y1 - strArray[0][Nstr].y0;
       DltNstrNKh = DltNstrN*DeltaKh/100;  //=DltNstrN*ncolumns/srcW*srcH/nrows;

         NWord = strArray[0][Nstr].wordArray.size();
         for ( Nwrd=0; Nwrd < NWord; Nwrd++ ){ // Цикл по количеству квадратиков NWord

             /// получение координат прямоугольников и точек из структуры по x по y
             wordOCR *wP=&strArray[0][Nstr].wordArray[Nwrd];
             // x0,x1, y0,y1 координаты квадрата вокруг буквы
             x0 = wP->x0;    x1 = wP->x1;    y0 = wP->y0;    y1 = wP->y1;

             // получение области поиска стеков - прямоугольников
             s0=y0-(y1-y0);     s1=y0-(y1-y0)/15;  // /10 s1=y0-(y1-y0)/9;  //s0=2*y0-y1-(y1-y0)/4;
             s3=x0+(x1-x0)/10;  s4=x1-(x1-x0)/9;  //s4 /8    //s3=x0+(x1-x0)/8;

             // LimY1 нижний лимит строки
             LimY1=strArray[0][Nstr].LimY1;
             if ( s0 < LimY1 ) { s5=LimY1; }
             if ( s0+(s1-s0)/2 < LimY1 ) { s5=s0+(s1-s0)/2; }
             if ( s0 > LimY1 ) { s5=s0; }
             s0=s5;

             // проверка выхода области поиска стеков за граници массива
             if ( s0 <  1 ) { s0=s1=1; }    if ( s1 > nrows-2 ) { s0=s1=nrows-1; }
             if ( s3 <  1 ) { s3=s4=1; }    if ( s4 > ncolumns-2) { s3=s4=ncolumns-1; }

             // запись области поиска стеков - прямоугольников в структуру
             wP->xt0 = s3;   wP->xt1 = s4;   wP->yt0 = s0;   wP->yt1 = s1;

             // обнуление флага стека
             wP->stackFlag=0;

             /// заполнение массова стека BufW горизонтальными суммами
             p=maxres=0;  BufW.assign(nrow,0);
             for ( y=s0; y < s1; y++ ) {        // вертикальный цикл
                 res=0; d=(y*ncolumns);
                 for ( x=s3; x < s4; x++ ) {    // горизонтальный цикл
                       res+=bits_data[d + x];
                 // визуализация (серым) области поиска стеков
#ifdef DEBUGLVL
if ( GrafT[6][1] ) { drawData[0][y][x]*=0.8; }  // визуализация (серым) ////
#endif
                   } // for x
                 BufW[p]=res<<6;   p++;      // *64 копирование в BufW
                 if ( p > nrow-2 ) { p=nrow-2; }
                 // получение максимума BufW[p]
                 if( res > maxres ) { maxres=res; }
             } // for y

             /// первичный отсев прямоугольников в которых заведомо нет стеков
             /// те практически отсев пустых прямоугольников

             // для улучшения быстродействия переходим к обработке следующей буквы Nwrd
             Prg1=(s1-s0)*(s4-s3)/200 + 1; // порог по нескольким пикселам (s1-s0)/12 + 1;
             Prg2=DeltaKh*(y1-y0)/(abs(x1-x0)+1)/10; // порог по прямоугольности области поиска
             if ( maxres < Prg1 || Prg2 > 15) { goto NwrdEND; }


             /// вторичный отсев прямоугольников те выдение прямоугольников
             /// которые имеет смысл более сложно обрабатывать (сглаживание BufW)

             //  сглаживание BufW ФИЛЬТР НИЗКИХ ЧАСТОТ
			 SP->filterHigh(BufW,DltNstrN/3);   //  /2 /4


			 // получение максимума сглаживанной (SP->filterHigh) функции BufW[у]
             maxres=0;
             for ( y=0; y < p; y++ ) {
                 if( BufW[y] > maxres ) { maxres=BufW[y]; }
             } // for y

             // и переход к обработке следующей буквы Nwrd для дальнейшего
             // улучшения быстродействия
             Prg1=32*(s4-s3)/6 + 1;  // /7 порог по ширине области поиска стеков (s1-s0)*(s4-s3)/5 + 1;
             if ( maxres < Prg1 ) { goto NwrdEND; }
             else {
             // рисует горизонтальную черную черту ниже стека
#ifdef DEBUGLV
if( GrafT[6][2] ) {
             for (x=0; x <= s4-s3; x++) { drawData[0][y0-(y1-y0)-2][(x+s3)]*=0.1; }
///          DM(maxres<<" maxres ")  DM(Prg1<<" Prg1 ") DM(END);  ///
}
#endif
             } // else
/**/

             // Запуск подпрограммы определения параметров стеков
             StackArgument(BufW, DltNstrN, s0, s1, s3, s4);

             // Запуск подпрограммы определения параметров букв
             WorldArgument(BufW, DltNstrN, x0, x1, y0, y1);

/*
#ifdef DEBUGLVL
// функции рисования вертикальных сглаженных графиков BufS точками
for (y=0; y < p; y++) { drawData[0][y+s0][(BufS[y]/32+s3)]*=0.1; }  ///
// функции рисования порога Prg1 вертикальной пунктирной чертой
for (y=0; y < p; y+=2) { drawData[0][y+s0][(Prg1/32+s3)]*=0.4; }    ///
// DM(maxres<<" maxres "); DM(Prg1<<" Prg1 "); DM(prg<<" prg ");
#endif
*/
             // переход к обработке следующей буквы Nwrd  // {break;}
                                 NwrdEND:;

         } // for Nwrd  // Цикл по количеству букв Nwrd

   } // for Nstr // Цикл по количеству строк NStrok


////////////////////////////////////////////////////////////////////////////////


// x0,y0,x1,y1
// x0,y0 координаты левого нижнего угла квадратика строки (слога, буквы).
// x1,y1 координаты правого верхнего угла квадратика строки (слога, буквы).

/**/

#ifdef DEBUGLVL

//DM(END);  DM(1111<<" correctLetterH ") DM(DltNstrN<<" DltNstrN ")
//DM(DltNstrNKh<<" DltNstrNKh ") DM(nrow<<" nrow ") DM(END);

       // Визуализация букв темно синими квадратиками из структур //
///                   wordDraw(0x00AA0011);  // темно синий
#endif

/**/

}//_____________________________________________________________________________

                           // Stack //

//  ----------------------------------------------------------------------------
// Запуск подпрограммы определения параметров стеков
//  ----------------------------------------------------------------------------
void GBitset::StackArgument(vector<int> &BufW, int DltNstrN,
                            int s0, int s1, int s3, int s4 ){


  int y,x,p,s5,s6,s7,sx;
  int res, res1, maxres, prg;  // , PGrad, prgY
  int nrow=BufW.size();  // size
  int w=ncolumns;
  bool d,*d1,*d2,*d3,*d4,*d5,*d6,*d7;

       // получение области усиления поиска стеков - прямоугольников
       s5=s1-(s1-s0)/3;   s6=s1-(s1-s0)/8;   s7=s1-(s1-s0)*3/4;
       sx=s4-(s4-s3)/3;

////   int n;
////   for ( n=0; n < 10000; n++ ) {
   // выделение граници в один пиксел, независимо от толщины штриха буквы
   // диагональный фильтр (не замечает нижней диагональной палки Тиб. НЯ, ДА )
   p=maxres=0;  BufW.assign(nrow,0);
   for (y=s0; y<s1-1; y++){
       d1=A+y*w;        //A[y][x]                         //       -1
     //d2=d1+w;         //A[y+1][x]                       //       2
     //d3=d1-w;         //A[y-1][x]                       //     -1
     //d4=d1+1;         //A[y][x+1]
     //d5=d1-1;         //A[y][x-1]
       d6=d1+1+w;       //A[y+1][x+1] //
       d7=d1-1-w;       //A[y-1][x-1] //
       res=0;
       for (x=s3+1; x<=sx; x++){
           //  выделение граници штриха буквы в один пиксел
           // A[y-4][x-4] =4*A[y][x]-A[y+2][x]-A[y-2][x]-A[y][x+2]-A[y][x-2]
           ////    d=*(d1+x)*6-*(d2+x)-*(d3+x)-*(d4+x)-*(d5+x)-*(d6+x)-*(d7+x);
           d=*(d1+x)*2-*(d6+x)-*(d7+x); //w<<1
           res+=d;
           // визуализация частей букв в окошке в виде граници в один пиксел
#ifdef DEBUGLVL
if ( GrafT[6][1] ) { drawData[0][y][x]=255+d*196; }  // draw it   *(d+x)
#endif
/**/
       }  // for x
////      } // n   
        
       res1=0;
       for (x=sx; x<s4-1; x++){
           //  выделение граници штриха буквы в один пиксел
           d=*(d1+x)-*(d6+x);                             //       -1
           res1+=d;                                       //       1
           // визуализация частей букв в окошке в виде граници в один пиксел
#ifdef DEBUGLVL
if ( GrafT[6][1] ) { drawData[0][y][x]=255+d*196; }  // draw it   *(d+x)
#endif
/**/
       }  // for x

     if ( y > s5 && y < s6 ) {
            BufW[p]=192*res + 64*res1*2/3; }  // || y < s7  192
     else { BufW[p]= 96*res + 64*res1*2/3; }  // *64 копирование в BufW  96
     p++;   if ( p > nrow-2 ) { p=nrow-2; }

    }  // for y
/**/

       // сглаживание HBuf ФИЛЬТР НИЗКИХ ЧАСТОТ
	   SP->filterHigh(BufW,DltNstrN/3);  // /2 /4

	   // получение максимума сглаживанной (SP->filterHigh) функции BufW[у]
       maxres=0;
       for ( y=0; y < p;  y++ ) {
           if( BufW[y] > maxres ) { maxres=BufW[y];   }  // prgY=y+s0;
       } // for y

       /// получение координаты *wP из структуры
       wordOCR *wP=&strArray[0][Nstr].wordArray[Nwrd];
       // запись максимума функции BufW[у] в структуру
       wP->Param1=maxres;


#ifdef DEBUGLVL
if( GrafT[6][1] ) {
// функции рисования вертикальных графиков BufW точками  // y < p,nrow
for (y=0; y < p; y++) { drawData[0][y+s0][(BufW[y]/32+s3)]*=0.1; }

// функции рисования порога Prg1 вертикальной пунктирной чертой
///for (y=0; y < p; y+=2) { drawData[0][y+s0][(prg/32+s3)]*=0.4; }

// рисует горизонтальную черту до пересечения порога Prg1 с функцией BufW[у]
///for (x=0; x <= prg/32; x++) { drawData[0][prgY][(x+s3)]*=0.4; }

// DM(END); DM(5555<<" StackDetector ");DM(maxres<<" maxres "); DM(prg<<" prg ")
}
#endif
/**/

//      d=*(d1+x)-*(d6+x);  //  -*(d7+x)
////    d=*(d1+x)*6-*(d2+x)-*(d3+x)-*(d4+x)-*(d5+x)-*(d6+x)-*(d7+x);
///     d=*(d1+x)*4-*(d2+x)-*(d3+x)-*(d6+x)-*(d7+x);
}//_____________________________________________________________________________


                            // World //

//  ----------------------------------------------------------------------------
// Запуск подпрограммы определения параметров букв
//  ----------------------------------------------------------------------------
void GBitset::WorldArgument(vector<int> &BufW, int DltNstrN,
                            int x0, int x1, int y0, int y1 ){


  int y,x,p;
  int res, maxres;
  int nrow=BufW.size();  // size
  int w=ncolumns;
  bool d,*d1;
  bool *d2,*d3,*d4,*d5;

   // выделение граници в один пиксел, независимо от толщины штриха буквы
   // вертикальный фильтр
   p=maxres=0;  BufW.assign(nrow,0);
   for (y=y0; y<y1-1; y++){
       d1=A+y*w;        //A[y][x]                         //      -1
       d2=d1+w;         //A[y+1][x]                       //       1
     //d3=d1-w;         //A[y-1][x]
     //d4=d1+1;         //A[y][x+1]
     //d5=d1-1;         //A[y][x-1]
       res=0;
       for (x=x0+1; x<x1-1; x++){
           //  выделение граници штриха буквы в один пиксел
           d=*(d1+x)-*(d2+x);   //  -*(d3+x)-*(d4+x)-*(d5+x)
           res+=d;
           // визуализация частей букв в окошке в виде граници в один пиксел
#ifdef DEBUGLVL
if ( GrafT[6][2] ) { drawData[0][y][x]=255+d*196; }  // draw it   *(d+x)
#endif
/**/
       }  // for x
       BufW[p]=res<<8;   p++;     // res<<8  *256 копирование в BufS
       if ( p > nrow-2 ) { p=nrow-2; }
    }  // for y


     // сглаживание HBuf ФИЛЬТР НИЗКИХ ЧАСТОТ
	 SP->filterHigh(BufW,DltNstrN/3);  // /2 /4

     // получение максимума сглаживанной (SP->filterHigh) функции BufW[у]
     maxres=0;   //  DltNstrN/2
     for ( y=0; y < p;  y++ ) {
         if( BufW[y] > maxres ) { maxres=BufW[y];   }  // prgY=y+s0;
     } // for y

     /// получение координаты *wP из структуры
     wordOCR *wP=&strArray[0][Nstr].wordArray[Nwrd];
     // запись максимума функции BufW[у] в структуру
     wP->Param2=maxres;

/**/
#ifdef DEBUGLVL
if( GrafT[6][2] ) {
// функции рисования вертикальных графиков BufW точками  // y < p,nrow
for (y=0; y < p; y++) { drawData[0][y+y0][(BufW[y]/32+x0)]*=0.1; }
}
#endif
/**/

}//_____________________________________________________________________________

                            // Flag //

//  ----------------------------------------------------------------------------
// Запуск подпрограммы окончательного определения наличия стеков
//  ----------------------------------------------------------------------------
  void GBitset::FlagStackDetector(){

  int y,x,p;            // ,m,n
  int s0,s1,s3,s4;
  int NWord,prg,prgStat,maxres; // res,


   int NStrok = strArray->size();
   for ( Nstr=0; Nstr < NStrok; Nstr++ ){ // Цикл по количеству строк NStrok

        prg=p=0;
        NWord = strArray[0][Nstr].wordArray.size();
        for ( Nwrd=0; Nwrd < NWord; Nwrd++ ){ // Цикл по количеству квадратиков вдоль строки NWord
            wordOCR *wP=&strArray[0][Nstr].wordArray[Nwrd];
            // получение максимума сглаживанной функции BufS[у]
            s3 = wP->xt0;  s4 = wP->xt1;  maxres = wP->Param2;
            if ( maxres > 0 ) { prg+=maxres;  p++; }

        } // Nwrd   // Цикл по количеству квадратиков вдоль строки NWord
        /// DM(END); DM(prg<<" prg ");  DM(p<<" p ") DM(END);

           // порог по ширине области коррекции 35
           prgStat=128*(s4-s3)*0.34 + 1;  // *34/100

           if ( p > 0 ) {
             // средний порог по строке по максимумому функции BufS
             prg=prg/p*0.35 + 1;   // *4/10 - порог  0,4
             /// для малого колличества стеков в строке комплексируем пороги
             prg=(1*prgStat + p*prg)/p;   ////   ////
           }
           else { prg=prgStat; }

        for ( Nwrd=0; Nwrd < NWord; Nwrd++ ){ // Цикл по количеству квадратиков вдоль строки NWord
            wordOCR *wP=&strArray[0][Nstr].wordArray[Nwrd];
            maxres = wP->Param1;        wP->stackFlag=0;
            // определение наличия стеков
            if ( maxres > prg ) { wP->stackFlag=1; }


#ifdef DEBUGLVL
if ( GrafT[6][1]!=0 && maxres > 1 ) {
    s0 = wP->yt0;  s1 = wP->yt1; s3 = wP->xt0; s4 = wP->xt1;
  // функции рисования порога prg вертикальной пунктирной чертой
    for (y=0; y < s1-s0; y+=2) { drawData[0][y+s0][(prg/32+s3)]*=0.4; }
  // рисует горизонтальную черную черту ниже стека
    ///for (x=0; x <= s4-s3; x++) { drawData[0][s0-4][(x+s3)]*=0.1;
    ///                             drawData[0][s0-5][(x+s3)]*=0.1; }
  // DM(END);  DM(maxres<<" maxres "); DM(prg<<" prg ");
} // if
#endif

        } // Nwrd   // Цикл по количеству квадратиков вдоль строки NWord

   } // for Nstr  // Цикл по количеству строк NStrok

/**/

}//_____________________________________________________________________________





/*
////////////////////////////////////////////////////////////////////////////////
      // Запуск подпрограммы вычисления средней толщины штриха в пределах буквы.
//                    GlyphLineDetector();

//  ----------------------------------------------------------------------------
// Запуск подпрограммы вычисления средней ширины вертикального штриха в пределах
// буквы.
//  ----------------------------------------------------------------------------
void GBitset::GlyphLineDetector(){


  int y,x,m,n,s0,s1,s3,s4,v;
  int x0,x1,y0,y1;
  int NWord,res,res01;
  // int w=ncolumns,h=nrows;    // ширина, высота  масштаб по ширине, высоте
  bool *p,*d;
//  vector<int> BufHelp(ncolumns);



//TIME_START


//        p=A+y*w+x;  // адрес A+y*w+x
//        b=*p;       // b=*(A+y*w+x);
//        b3=*(p+m)+*(p-m)+*(p+n)+*(p-n)+*(p+m+n)+*(p-m+n)+*(p+m-n)+*(p-m-n);// * значение по адресу

         // для визуализации одной строки заремачить цикл по Nstr (глобальная).
         Nstr=2;

///   for ( Nstr=0; Nstr < strArray->size(); Nstr++ ){ // Цикл по количеству строк NStrok

        NWord = strArray[0][Nstr].wordArray.size();
        for ( Nwrd=0; Nwrd < NWord; Nwrd++ ){ // Цикл по количеству квадратиков вдоль строки NWord
            wordOCR *wP=&strArray[0][Nstr].wordArray[Nwrd];
            // x0,x1, y0,y1 координаты квадрата вокруг буквы
            x0 = wP->x0;    x1 = wP->x1;    y0 = wP->y0;    y1 = wP->y1;

            res=res01=0;
            for ( y=y0; y < y1; y++ ) { // горизонтальный цикл
                d=A+y*ncolumns;   //  p=A+y*w;  d=y*ncolumns;
                for ( x=x0; x < x1-1; x++ ) {
                    //res+=bits_data[d + x];
                    p=d+x;
                    res+=*p;
                    *p=*(p+1)-*p;  res01+=*p; // эквивалентно if(*(p+1)-*p !=0) res01++;

                    ///*p=*(p+1)-*p;  res01+=*p;
                    ///res01+=(*(p+1)-*p)&01;   // v=*(p+1)-*p;   res01+=v&01;
                    ///if ( *(p+1)-*p != 0 )  res01++;

// визуализация (серым) области поиска стеков - прямоугольников
////   drawData[0][y][x]*=0.8;      // визуализация //
                    } // for x
            } // for y

////            DM(res<<" res "); DM(res01<<" res01 ");

        } // Nwrd   // Цикл по количеству квадратиков вдоль строки NWord

////       DM(END);

///   } // for Nstr  // Цикл по количеству строк NStrok




// n&01 устанвливает в нуль все двоичные разряды числа n, кроме первого, соотетствующего 0 или 1
// При сдвиге вправо метод заполнения освобождающихся левых битов зависит от
// типа первого операнда. Если тип unsigned, то свободные левые биты
// устанавливаются в нуль. Модификатор типа unsigned указывает, что переменная
// принимает неотрицательные значения. При этом самый левый бит области памяти,
// выделяемой для хранения значения используется так же, как и все остальные биты
//  <<6

 for ( x=-4; x < 5; x++ ) {
///      DM(END);  DM(x<<" x ");
      v=x&01;   //v=v>>1;
///      DM(v<<" v ");  DM(END);
 } // for x




#ifdef DEBUGLVL
// DM(END);  DM(srcH<<" srcH ")  DM(END);
#endif
//TIME_PRINT

//  elememtOCR, levelA, levelB
//  y = (a>b) ? a: b;  т.е. y = max(a, b).
//  y = x ? a: b;  т.е.  y = a, если x не равно нулю, и y = b, если х равно нулю.

//  abs(DeltaK);
}//_____________________________________________________________________________
////////////////////////////////////////////////////////////////////////////////
*/

////////////////////////////////////////////////////////////////////////////////

//  elememtOCR, levelA, levelB
//  y = (a>b) ? a: b;  т.е. y = max(a, b).
//  y = x ? a: b;  т.е.  y = a, если x не равно нулю, и y = b, если х равно нулю.
//  abs(DeltaK);




/*
  int y,x,p;
  int res, maxres, prg, prgY, PGrad;
  int nrow=BufS.size();  // size
  int w=ncolumns;
  bool d,*d1,*d2,*d3,*d4,*d5;


   // выделение граници в один пиксел, независимо от толщины штриха буквы
   p=maxres=0;  BufS.assign(nrow,0);
   for (int y=s0+1; y<s1-1; y++){
       d1=A+y*w;        //A[y][x]                         //      -1
       d2=d1+w;         //A[y+1][x]                       //    -1 4-1
       d3=d1-w;         //A[y-1][x]                       //      -1
       d4=d1+1;         //A[y][x+1]
       d5=d1-1;         //A[y][x-1]
       res=0;
       for (int x=s3+1; x<s4-1; x++){
           //  выделение граници штриха буквы в один пиксел
           // A[y-4][x-4] =4*A[y][x]-A[y+2][x]-A[y-2][x]-A[y][x+2]-A[y][x-2]
           d=*(d1+x)*4-*(d2+x)-*(d3+x)-*(d4+x)-*(d5+x);  // *(d+x)
           res+=d;

          #ifdef DEBUGLVL
          // визуализация частей букв в окошке в виде граници в один пиксел
          drawData[0][y][x]=255+d*196;  // draw it   *(d+x)
          #endif

           }  // for x
       BufS[p]=res<<6;   p++;       // *64 копирование в BufS
       if ( p > nrow-2 ) { p=nrow-2; }
    }  // for y
*/

/////////////////////////////////////////

/*
  int y,x,p;
  int res, maxres, prg, prgY, PGrad;
  int nrow=BufS.size();  // size
  int w=ncolumns;
  bool d,*d1,*d2,*d3,*d4,*d5,*d6,*d7;


   // выделение граници в один пиксел, независимо от толщины штриха буквы
   p=maxres=0;  BufS.assign(nrow,0);
   for (int y=s0+1; y<s1-1; y++){
       d1=A+y*w;        //A[y][x]                         //      -1-1
       d2=d1+w;         //A[y+1][x]                       //    -1 6-1
       d3=d1-w;         //A[y-1][x]                       //    -1-1
       d4=d1+1;         //A[y][x+1]
       d5=d1-1;         //A[y][x-1]
       d6=d2+1;         //A[y+1][x+1] //
       d7=d3-1;         //A[y-1][x-1] //
       res=0;
       for (int x=s3+1; x<s4-1; x++){
           //  выделение граници штриха буквы в один пиксел
           // A[y-4][x-4] =4*A[y][x]-A[y+2][x]-A[y-2][x]-A[y][x+2]-A[y][x-2]
           d=*(d1+x)*6-*(d2+x)-*(d3+x)-*(d4+x)-*(d5+x)-*(d6+x)-*(d7+x);
    ///       d=*(d1+x)*2-*(d6+x)-*(d7+x);
           res+=d;

          #ifdef DEBUGLVL
          // визуализация частей букв в окошке в виде граници в один пиксел
          drawData[0][y][x]=255+d*196;  // draw it   *(d+x)
          #endif

           }  // for x
       BufS[p]=res<<6;   p++;       // *64 копирование в BufS
       if ( p > nrow-2 ) { p=nrow-2; }
    }  // for y
*/


/* ///////  СОХРАНЯЕМ для малого колличества стеков в строке  ///////
       prg=32*(s4-s3)*35/100 + 1; // *32 *44 *(s1-s0) // prg порог по ширине области коррекции
       if ( maxres > prg ) { // && prgY<s1-(s1-s0)/4
           // определения наличия стеков
           wP->stackFlag=1;
 // рисует горизонтальную черную черту ниже стека
 ///      for (x=0; x <= s4-s3; x++) { drawData[0][y0-(y1-y0)-2][(x+s3)]*=0.1; }
 ///   DM(maxres<<" maxres ")  DM(prg<<" prg ") DM(END);  ///
       }
*/

/*
       //  DltNstrN/3
       // вычисление точки пересечения порога Prg1 с функцией BufS[у]
       prg=32*(s4-s3)*35/100 + 1; // *33 *44 *(s1-s0) // prg порог по ширине области коррекции
       for ( y=0; y < p; y++ ) {
           if ( BufS[y] > prg) {
           // определения наличия стеков
           wP->stackFlag=1;
//           prgY=y+s0;
           break;
           }
       } // for y
*/
